package com.yunshipei.core.net;

import android.text.TextUtils;

import java.lang.reflect.Field;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;

public final class EnterClient {

    private static final int DEFAULT_TIMEOUT = 10;

    private OkHttpClient mManagerClient;
    private OkHttpClient mHubClient = new OkHttpClient.Builder().connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).build();

    private List<Cookie> mCookieList = new ArrayList<>();

    private EnterClient() {
        initSSLClient(mHubClient);
    }

    private static final class EnterClientInner {
        private static final EnterClient instance = new EnterClient();
    }

    public static EnterClient getInstances() {
        return EnterClientInner.instance;
    }

    public void initManagerClient(String cookieUrl, String proxyIP, int proxyPort) {
        if (!TextUtils.isEmpty(proxyIP) && proxyPort != 0) {
            OkHttpClient.Builder builder = configManagerClientBuilder(cookieUrl);
            Proxy proxy = new Proxy(java.net.Proxy.Type.HTTP, new InetSocketAddress(proxyIP, proxyPort));
            mManagerClient = builder.proxy(proxy).build();
        } else {
            mManagerClient = configManagerClientBuilder(cookieUrl).build();
        }
        initSSLClient(mManagerClient);
    }

    private OkHttpClient.Builder configManagerClientBuilder(final String cookieUrl) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS).readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
        builder.cookieJar(new CookieJar() {
            @Override
            public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                if (!TextUtils.isEmpty(cookieUrl) && url.toString().equals(cookieUrl) && cookies != null && cookies.size() > 0) {
                    mCookieList = cookies;
                }
            }

            @Override
            public List<Cookie> loadForRequest(HttpUrl url) {
                return mCookieList;
            }
        });
        return builder;
    }

    public List<Cookie> getManagerCookies() {
        return mCookieList;
    }

    //获取hub的请求client
    public OkHttpClient getHubClient() {
        return mHubClient;
    }

    //获取manager的请求的client，可能设置过代理，可能清空过代理
    public OkHttpClient getManagerClient() {
        return mManagerClient;
    }

    public void initSSLClient(OkHttpClient client) {
        SSLContext sc = null;
        try {
            sc = SSLContext.getInstance("SSL");
            sc.init(null, new TrustManager[]{new X509TrustManager() {
                @Override
                public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {

                }

                @Override
                public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {

                }

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            }}, new SecureRandom());
        } catch (Exception e) {
            e.printStackTrace();
        }

        HostnameVerifier hv1 = new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        String workerClassName = "okhttp3.OkHttpClient";
        try {
            Class workerClass = Class.forName(workerClassName);
            Field hostnameVerifier = workerClass.getDeclaredField("hostnameVerifier");
            hostnameVerifier.setAccessible(true);
            hostnameVerifier.set(client, hv1);
            Field sslSocketFactory = workerClass.getDeclaredField("sslSocketFactory");
            sslSocketFactory.setAccessible(true);
            sslSocketFactory.set(client, sc.getSocketFactory());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
